package aole;

import aole.Main2.hit_type;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Main extends Application {
	private StringProperty						team1;
	private StringProperty						team2;

	private StringProperty						battingTeam;

	private PlayerMatchInfo						striker;
	private PlayerMatchInfo						nonStriker;

	private ObservableList< PlayerMatchInfo >	data;
	private ObservableList< PlayerMatchInfo >	data1;
	private ObservableList< PlayerMatchInfo >	data2;
	private TableView< PlayerMatchInfo >		table;

	private int									inings;
	private int									winner;
	private int									totalRuns;
	private int									totalBalls;
	private int									totalWickets;
	private int									playersIn;
	private int									lastTotal;
	private boolean								matchComplete;
	private int									overs;
	private int									balls;

	private Label								lblScore	= new Label();

	private Timeline							timeline;

	@Override
	public void start( Stage stage ) throws Exception {
		// create UI
		BorderPane root = new BorderPane();
		Scene scene = new Scene( root, 800, 600 );

		showStartScreen( root );

		stage.setScene( scene );
		stage.show();
	}

	private void showStartScreen( final BorderPane root ) {
		Label l = new Label( "Enter team names" );

		Label t1 = new Label( "Team 1:" );
		TextField txt1 = new TextField( "Team1" );
		team1 = new SimpleStringProperty();
		team1.bind( txt1.textProperty() );
		HBox hbox1 = new HBox( 5 );
		hbox1.getChildren().addAll( t1, txt1 );

		Label t2 = new Label( "Team 2:" );
		TextField txt2 = new TextField( "Team2" );
		team2 = new SimpleStringProperty();
		team2.bind( txt2.textProperty() );
		HBox hbox2 = new HBox( 5 );
		hbox2.getChildren().addAll( t2, txt2 );

		Button b = new Button( "Start Match" );
		b.setOnAction( new EventHandler< ActionEvent >() {

			@Override
			public void handle( ActionEvent ae ) {
				// toss
				// start the batting/bowling
				showMatchScreen( root );
				showMatchControls( root );
				inings = 0;
				matchComplete = false;
				resetInings();
			}
		} );

		VBox vbox = new VBox( 5 );
		vbox.getChildren().addAll( l, hbox1, hbox2, b );

		Group g = new Group( vbox );
		root.setCenter( g );
	}

	protected void showMatchControls( BorderPane root ) {
		HBox hbox = new HBox();
		hbox.getChildren().addAll( lblScore );

		root.setBottom( hbox );

		// right pane
		Button i1 = new Button( "1st Inings" );
		i1.setOnAction( new EventHandler< ActionEvent >() {

			@Override
			public void handle( ActionEvent arg0 ) {
				battingTeam.set( team1.get() );
				table.setItems( data1 );
			}

		} );

		Button b = new Button( "Play" );
		b.setOnAction( new EventHandler< ActionEvent >() {

			@Override
			public void handle( ActionEvent ae ) {
				timeline = new Timeline( new KeyFrame( Duration.ZERO,
						new EventHandler< ActionEvent >() {
							@Override
							public void handle( ActionEvent event ) {
								bowlNextBall();
							}
						} ), new KeyFrame( Duration.millis( 100 ) ) );
				timeline.setCycleCount( Timeline.INDEFINITE );
				timeline.play();
			}
		} );
		Button i2 = new Button( "2nd Inings" );
		i2.setOnAction( new EventHandler< ActionEvent >() {

			@Override
			public void handle( ActionEvent arg0 ) {
				battingTeam.set( team2.get() );
				table.setItems( data2 );
			}

		} );

		VBox vbox = new VBox();
		vbox.getChildren().addAll( b, i1, i2 );

		root.setRight( vbox );
	}

	private void resetInings() {
		if( inings == 0 ) {
			data = data1;
			table.setItems( data1 );
			battingTeam.set( team1.get() );
		} else {
			data = data2;
			table.setItems( data2 );
			battingTeam.set( team2.get() );
		}
		totalRuns = totalBalls = totalWickets = playersIn = overs = balls = 0;
	}

	protected void bowlNextBall() {
		int run;

		if( playersIn == 0 ) {
			// new inings
			striker = new PlayerMatchInfo( "Player1" );
			striker.setStatus( "*" );
			nonStriker = new PlayerMatchInfo( "Player2" );
			data.add( striker );
			data.add( nonStriker );
			playersIn = 2;
		}

		run = getRuns(getHitType());
		striker.addBalls( 1 );
		totalBalls++;

		// out
		if( run < 0 ) {
			totalWickets++;
			striker.setStatus( "out" );
			if( totalWickets < 10 ) {
				striker = new PlayerMatchInfo( "Player" + ++playersIn );
				striker.setStatus( "*" );
				data.add( striker );
			} else {
				if( inings == 0 ) {
					lastTotal = totalRuns;
					inings = 1;
					resetInings();
				} else {
					matchComplete = true;
					if( totalRuns == lastTotal )
						winner = -1;
					else winner = 0;
				}
			}
		} else {
			striker.addRuns( run );
			totalRuns += run;
		}

		// made more runs
		if( inings == 1 && totalRuns > lastTotal ) {
			matchComplete = true;
			winner = 1;
		} else {
			// crease change
			if( run == 1 || run == 3 ) {
				PlayerMatchInfo p = striker;
				striker = nonStriker;
				nonStriker = p;

				striker.setStatus( "*" );
				nonStriker.setStatus( "" );
			}
		}

		// overs completed
		if( totalBalls == 120 ) {
			if( inings == 0 ) {
				lastTotal = totalRuns;
				inings = 1;
				resetInings();
			} else {
				matchComplete = true;
				if( totalRuns > lastTotal )
					winner = 1;
				else if( totalRuns < lastTotal )
					winner = 0;
				else winner = -1;
			}
		}

		balls++;
		if( balls == 6 ) {
			// over complete
			overs++;
			balls = 0;

			PlayerMatchInfo p = striker;
			striker = nonStriker;
			nonStriker = p;

			striker.setStatus( "*" );
			nonStriker.setStatus( "" );
		}
		// refresh tableview
		table.getColumns().get( 0 ).setVisible( false );
		table.getColumns().get( 0 ).setVisible( true );

		String strScore = totalRuns + " for " + totalWickets + " in " + overs
				+ "." + balls;
		if( inings == 1 ) strScore += " | Target " + (lastTotal + 1);
		if( matchComplete ) {
			strScore += " | ";
			if( winner == -1 )
				strScore += "It's a TIE!";
			else if( winner == 0 ) {
				strScore += team1.get() + " won the match by "
						+ (lastTotal - totalRuns) + " runs.";
			} else strScore += team2.get() + " won the match by "
					+ (10 - totalWickets) + " wickets.";

			timeline.stop();
		}
		lblScore.setText( strScore );
	}

	private hit_type getHitType() {
		double r = Math.random();

		if( r < 0.05 ) {
			return hit_type.MissOut;
		}
		/*
		 * if( r < 2 / 8. ) { hitMissIn++; return hit_type.MissIn; }
		 */
		if( r < 0.20 ) {
			return hit_type.EdgeOut;
		}
		/*
		 * if( r < 4 / 8. ) { hitEdgeIn++; return hit_type.EdgeIn; }
		 */
		if( r < .65 ) {
			return hit_type.HalfOut;
		}
		/*
		 * if( r < 6 / 8. ) { hitHalfIn++; return hit_type.HalfIn; }
		 */
		return hit_type.Middle;
	}

	private int getRuns( hit_type ht ) {
		double r;
		boolean arial = false;
		boolean infield = false;
		boolean outfield = false;
		boolean slips_keeper = false;

		if( ht == hit_type.MissIn || ht == hit_type.MissOut ) {
			// the ball is completely missed
			// did it hit the stumps?
			r = Math.random();
			if( r < .25 ) return -1;
			return 0;
		}

		// was the shot arial?
		r = Math.random();
		if( r < .15 ) arial = true;
		// is there a fielder in infield
		r = Math.random();
		if( r < .35 ) infield = true;
		// is there a fielder in outfield
		r = Math.random();
		if( r < .50 ) outfield = true;

		if( ht == hit_type.Middle ) {
			if( arial ) return 6;
			// ground shot
			if( infield ) return 0;
			if( outfield ) return 1;
			return 4;
		}

		if( ht == hit_type.HalfIn || ht == hit_type.HalfOut ) {
			if( arial ) {
				if( outfield ) return -1;
				return 4;
			}
			// ground shot
			if( infield ) return 0;
			if( outfield ) return 1;
			return 2;
		}

		// did the ball goto slips or keeper?
		r = Math.random();
		if( r < .4 ) slips_keeper = true;

		if( ht == hit_type.EdgeIn || ht == hit_type.EdgeOut ) {
			if( arial ) {
				if( slips_keeper ) return -1;
				return 4;
			}
			if( slips_keeper ) return 0;

			// 75% chance of 1
			r = Math.random();
			if( r < .75 ) return 1;
			return 2;
		}
		return 0;
	}

	protected void showMatchScreen( BorderPane root ) {
		TableColumn< PlayerMatchInfo, String > playerCol = new TableColumn<>(
				"Player" );
		playerCol
				.setCellValueFactory( new PropertyValueFactory< PlayerMatchInfo, String >(
						"name" ) );
		TableColumn< PlayerMatchInfo, String > statusCol = new TableColumn<>(
				"" );
		statusCol
				.setCellValueFactory( new PropertyValueFactory< PlayerMatchInfo, String >(
						"status" ) );
		TableColumn< PlayerMatchInfo, String > runsCol = new TableColumn<>(
				"Runs" );
		runsCol.setCellValueFactory( new PropertyValueFactory< PlayerMatchInfo, String >(
				"runsInfo" ) );
		TableColumn< PlayerMatchInfo, Double > rateCol = new TableColumn<>(
				"Strike Rate" );
		rateCol.setCellValueFactory( new PropertyValueFactory< PlayerMatchInfo, Double >(
				"strikeRate" ) );

		data1 = FXCollections.observableArrayList();
		data2 = FXCollections.observableArrayList();

		table = new TableView<>();
		table.getColumns().addAll( playerCol, statusCol, runsCol, rateCol );

		battingTeam = new SimpleStringProperty();
		Label l1 = new Label();
		l1.textProperty().bind( battingTeam );

		VBox vbox = new VBox();
		vbox.getChildren().addAll( l1, table );

		Group g = new Group( vbox );
		root.setCenter( g );
	}

	public static void main( String[] args ) {
		launch( args );
	}

}